package br.com.util.lov;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import br.com.util.exception.UtilException;
import br.com.util.hibernate.business.NegocioThrow;
import br.com.util.tipodado.Inteiro;
import br.com.util.tipodado.InteiroLongo;
import br.com.util.util.Conexao;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class ListaNgc
{
	private static ListaNgc instancia = null;
	private static HashMap parametros;
	
	private ListaNgc() throws UtilException
	{
		inicializarParametros();
	}
	
	public static ListaNgc getInstancia() throws UtilException
	{
		if (instancia == null)
		{
			instancia = new ListaNgc();
		}
		return instancia;
	}
	
	public ParametroListaVo getParametro(String tipoLista)
	{
		return (ParametroListaVo) parametros.get(tipoLista);
	}

	public Collection getLista(ParametroListaVo parListaVo, String vlrConsulta)
			throws UtilException
	{
		Connection conn = Conexao.getConexao();
		try
		{
			Inteiro numeroMaxRegistros = new Inteiro(200);
			parListaVo.setNumeroMaxRegistros(numeroMaxRegistros);
			return ListaPrs.getInstancia().getLista(conn, parListaVo, vlrConsulta, new InteiroLongo(200));
		} finally
		{
			Conexao.fechaConexao(conn);
		}
	}

	public String getDescricao(ParametroListaVo parListaVo, String codigo)
			throws UtilException
	{
		Connection conn = Conexao.getConexao();
		try
		{
			return this.getDescricao(conn, parListaVo, codigo);
		} finally
		{
			Conexao.fechaConexao(conn);
		}
	}

	public String getDescricao(Connection conn, ParametroListaVo parListaVo,
			String codigo) throws UtilException
	{
		return ListaPrs.getInstancia().getDescricao(conn, parListaVo, codigo);
	}

	public String getDescricao(String nomeParametro, int codigo)
			throws UtilException
	{
		return this.getDescricao(nomeParametro, String.valueOf(codigo));
	}

	public String getDescricao(Connection conn, String nomeParametro, int codigo)
			throws UtilException
	{
		return this.getDescricao(conn, nomeParametro, String.valueOf(codigo));
	}

	public String getDescricao(String nomeParametro, long codigo)
			throws UtilException
	{
		return this.getDescricao(nomeParametro, String.valueOf(codigo));
	}

	public String getDescricao(Connection conn, String nomeParametro,
			long codigo) throws UtilException
	{
		return this.getDescricao(conn, nomeParametro, String.valueOf(codigo));
	}

	public String getDescricao(String nomeParametro, String codigo)
			throws UtilException
	{
		ParametroListaVo parListaVo = getParametro(nomeParametro);
		if (parListaVo != null)
		{
			return getDescricao(parListaVo, codigo);
		} else
		{
			return null;
		}
	}

	public String getDescricao(Connection conn, String nomeParametro,
			String codigo) throws UtilException
	{
		ParametroListaVo parListaVo = getParametro(nomeParametro);
		if (parListaVo != null)
		{
			return getDescricao(conn, parListaVo, codigo);
		} else
		{
			return null;
		}
	}

	public String getDescricao(String nomeParametro, String[] nomesFiltro,
			String[] valoresFiltro, String codigo) throws UtilException
	{
		Connection conn = Conexao.getConexao();
		try
		{
			return getDescricao(conn, nomeParametro, nomesFiltro, valoresFiltro, codigo);
		} catch (Exception e)
		{
			throw NegocioThrow.getInstancia().catchConsulta(e);
		} finally
		{
			Conexao.fechaConexao(conn);
		}
	}

	public String getDescricao(Connection conn, String nomeParametro,
			String[] nomesFiltro, String[] valoresFiltro, String codigo)
			throws UtilException
	{
		ParametroListaVo parListaVo = getParametro(nomeParametro);
		setFiltrosParametro(parListaVo, nomesFiltro, valoresFiltro);
		return getDescricao(conn, parListaVo, codigo);
	}

	public Collection getLista(String nomeParametro, String[] nomesFiltro,
			String[] valoresFiltro, String vlrConsulta)
			throws UtilException
	{
		ParametroListaVo parListaVo = getParametro(nomeParametro);
		setFiltrosParametro(parListaVo, nomesFiltro, valoresFiltro);
		return getLista(parListaVo, vlrConsulta);
	}

	public Collection getLista(String nomeParametro, String vlrConsulta)
			throws UtilException
	{
		ParametroListaVo parListaVo = getParametro(nomeParametro);
		if (parListaVo != null)
		{
			return getLista(parListaVo, vlrConsulta);
		} else
		{
			return null;
		}
	}

	private void setFiltrosParametro(ParametroListaVo parListaVo,
			String[] nomesFiltro, String[] valoresFiltro)
	{
		int i = 0;
		String retorno = null;
		if (parListaVo != null)
		{
			if (parListaVo.getFiltros() != null)
			{
				Iterator iterator = parListaVo.getFiltros().iterator();
				while (iterator.hasNext())
				{
					FiltroListaVo filtroVo = (FiltroListaVo) iterator.next();

					i = getIndice(filtroVo.getNome(), nomesFiltro);
					if (i >= 0 && valoresFiltro != null)
					{
						filtroVo.setValor(valoresFiltro[i]);
					} else
					{
						switch (filtroVo.getTipo())
						{
							case FiltroListaVo.STRING:
								filtroVo.setValor("");
								break;
							default:
								filtroVo.setValor("0");
								break;
						}
					}
				}
			}
		}
	}

	private int getIndice(String nome, String[] lista)
	{
		if (lista != null)
		{
			for (int i = 0; i < lista.length; i++)
			{
				if (nome.equalsIgnoreCase(lista[i]))
				{
					return i;
				}
			}
		}
		return -1;
	}
	
	private void inicializarParametros() throws UtilException
	{
		XStream xstream = new XStream(new DomDriver());

		xstream.alias("parametro", ParametroListaVo.class);
		xstream.alias("filtro", FiltroListaVo.class);
		xstream.alias("identificador", String.class);
		xstream.alias("parametros", HashMap.class);
		xstream.alias("filtros", ArrayList.class);

		try
		{
			InputStream is = this.getClass().getClassLoader().getResource("lista-config.xml").openStream();
			InputStreamReader isr = new InputStreamReader(is);
			
			parametros = (HashMap) xstream.fromXML(isr);
		}
		catch (FileNotFoundException fnfe)
		{
			throw new UtilException(fnfe);
		}
		catch (IOException ioe)
		{
			throw new UtilException(ioe);
		}
	}

}
